#include "ZText.h"

namespace Zdib
{
	CTextBase::CTextBase(CContainer *root,CContainer *parent,char *txt,HFONT font,TColor color):CContainer(parent)
	{
		m_Txt=NULL;
		m_Img=NULL;
		m_WTxt=NULL;
		SetRoot(root);
		m_VSpace=1;
		memset(&m_Mat2, 0, sizeof(MAT2));
		bitlist=NULL;
		m_Mat2.eM11.value = 1;
		m_Mat2.eM22.value = 1;
		m_Hdc=CreateCompatibleDC(root->GetHDC());
		//SetBkMode( m_Hdc, TRANSPARENT );
		//SetTextAlign( m_Hdc, TA_TOP | TA_LEFT );
		SetText(txt,false);
		SetTColor(color,false);
		SetHFont(font,false);
	}
	void CTextBase::SetText(char *txt,bool iscreate)
	{
		int txtlen;
		if(m_Txt!=NULL)
		{
			free(m_Txt);
			m_Txt=NULL;
		}
		if(m_WTxt!=NULL)
		{
			free(m_WTxt);
			m_WTxt=NULL;
		}
		
		txtlen=strlen(txt)+1;
		m_Txt=(char*)malloc(txtlen);
		memcpy(m_Txt,txt,txtlen);	
		m_WTxt=(wchar_t *)malloc(txtlen*sizeof(wchar_t));
		MultiByteToWideChar(CP_ACP,0,txt,txtlen,m_WTxt,txtlen);
		if(iscreate)
			CreateTextObj();
	}

	void CTextBase::SetTColor(TColor color,bool iscreate)
	{
		m_Color=color;
		m_BgColor=color;
		m_BgColor.r+=1;
		SetTextColor( m_Hdc, RGB(m_Color.r, m_Color.g, m_Color.b));
		if(iscreate)
			CreateTextObj();
	}
	TColor CTextBase::GetTColor()
	{
		return m_Color;
	}
	void CTextBase::SetHFont(HFONT font,bool iscreate)
	{
		TEXTMETRIC tm;
		m_Font=font;
		SelectObject( m_Hdc, m_Font );
		GetTextMetrics(m_Hdc,&tm);
		m_TextH=tm.tmAscent+tm.tmDescent;
		if(iscreate)
			CreateTextObj();
	}
	HFONT CTextBase::GetHFont()
	{
		return m_Font;
	}
	
	void CTextBase::CreateTextObj()
	{
		SIZE Size;  
		GLYPHMETRICS  m_metrics;
		PTrueTypeBit tempttb;
		int i,txtlen,bitsize;
		if(m_Img!=NULL)
		{
			delete m_Img;
			m_Img=NULL;
		}
		ClearBitList();
		Size.cx=0;
		Size.cy=m_TextH;
		txtlen=wcslen(m_WTxt);
		bitlist=new TZList(20);
		for(i=0;i<txtlen;i++)
		{
			bitsize=GetGlyphOutline(m_Hdc, m_WTxt[i], GGO_BITMAP, & m_metrics, 0, NULL, &m_Mat2);
			tempttb=new TTrueTypeBit;
			tempttb->len=bitsize;
			tempttb->w=m_metrics.gmBlackBoxX;
			tempttb->h=m_metrics.gmBlackBoxY;
			tempttb->bx=m_metrics.gmptGlyphOrigin.x;
			tempttb->by=m_metrics.gmptGlyphOrigin.y;
			tempttb->realw=max(m_metrics.gmCellIncX,m_metrics.gmptGlyphOrigin.x+(int)m_metrics.gmBlackBoxX)-min(0,m_metrics.gmptGlyphOrigin.x);
			tempttb->Bits=new BYTE[bitsize];
			Size.cx+=tempttb->realw+m_VSpace;
			bitsize=GetGlyphOutline(m_Hdc, m_WTxt[i], GGO_BITMAP, & m_metrics, tempttb->len, tempttb->Bits, &m_Mat2);
			bitlist->add((LPVOID)tempttb);
		}
		m_Img=new CImgFile();
		m_Img->SetSize(Size.cx,Size.cy);
		m_Img->FillColor(m_BgColor);
		int x,y,tempw;
		x=0;
		y=m_TextH;
		for(i=0;i<txtlen;i++)
		{
			tempttb=(PTrueTypeBit)bitlist->items(i);
			tempw=tempttb->len/tempttb->h;
			if(tempttb->by<tempttb->h)
				m_Img->DrawText256(x+tempttb->bx,y-tempttb->h,tempw,tempttb->h,tempttb->w,m_Color,tempttb->Bits);
			else
				m_Img->DrawText256(x+tempttb->bx,y-tempttb->by,tempw,tempttb->h,tempttb->w,m_Color,tempttb->Bits);
			x+=(tempttb->realw+m_VSpace);
		}
		m_Img->SetMake(true);
		ClearBitList();
		W=Size.cx;
		H=Size.cy;
	}

	char *CTextBase::GetText()
	{
		return m_Txt;
	}
	CTextBase::~CTextBase()
	{
		ClearBitList();
		DeleteDC(m_Hdc);
		delete m_Img;
		if(m_Txt!=NULL)
			free(m_Txt);
		if(m_WTxt!=NULL)
			free(m_WTxt);
	}
	
	void CTextBase::ClearBitList()
	{
		if(bitlist==NULL)
			return;
		int i;
		PTrueTypeBit pttb;
		for(i=bitlist->count-1;i>=0;i--)
		{
			pttb=(PTrueTypeBit)bitlist->items(i);
			delete []pttb->Bits;
			delete pttb;
		}
		delete bitlist;
		bitlist=NULL;
	}
	
	void CTextBase::Draw()
	{
		CImgFile *desimg;
		if(!m_Show)
			return;
		desimg=m_Parent->GetCurImg();
		if(desimg)
		{
 			if(m_RefrashDrawPos)
			{
				m_DPosValue=CalDrawPosValue(m_Img->GetWidth(),m_Img->GetHeight(),ScreenX,ScreenY);
			}
			desimg->Draw(m_Img,ScreenX,ScreenY,false,&m_DPosValue);
		}
		CContainer::Draw();
	}

	bool CTextBase::OnEvent(const TEvent& ev)
	{
		if(ev.event_type==ET_MouseEvent)
		{
			if(myEventReceiver!=NULL)
			{
				TEvent newev;
				newev=ev;
				newev.Mouse.Call=this;
				newev.Mouse.CallBack=NULL;
				return myEventReceiver->OnEvent(newev);
			}
			else
			{
				return m_Parent->OnEvent(ev);
			}
		}
		return false;
	}

	CText::CText(CContainer *root,CContainer *parent,char *txt,HFONT font,TColor color):CTextBase(root,parent,txt,font,color)
	{
		CreateTextObj();
	}

	CRichText::CRichText(CContainer *root,CContainer *parent,char *txt,int w,HFONT font,TColor color):CTextBase(root,parent,txt,font,color)
	{
		m_TextW=w;
		m_HSpace=1;
		CreateTextObj();
	}

	void CRichText::CreateTextObj()
	{
		SIZE Size;  
		GLYPHMETRICS  m_metrics;
		PTrueTypeBit tempttb;
		int i,txtlen,bitsize,tempW;
		if(m_Img!=NULL)
		{
			delete m_Img;
			m_Img=NULL;
		}
		ClearBitList();
		Size.cx=m_TextW;
		if(m_TextW<m_TextH)
		{
			Size.cx=m_TextH;
			m_TextW=m_TextH;
		}
		Size.cy=m_TextH+m_HSpace;
		tempW=0;
		txtlen=wcslen(m_WTxt);
		bitlist=new TZList(20);
		for(i=0;i<txtlen;i++)
		{
			bitsize=GetGlyphOutline(m_Hdc, m_WTxt[i], GGO_BITMAP, & m_metrics, 0, NULL, &m_Mat2);
			tempttb=new TTrueTypeBit;
			tempttb->len=bitsize;
			tempttb->w=m_metrics.gmBlackBoxX;
			tempttb->h=m_metrics.gmBlackBoxY;
			tempttb->bx=m_metrics.gmptGlyphOrigin.x;
			tempttb->by=m_metrics.gmptGlyphOrigin.y;
			tempttb->realw=max(m_metrics.gmCellIncX,m_metrics.gmptGlyphOrigin.x+(int)m_metrics.gmBlackBoxX)-min(0,m_metrics.gmptGlyphOrigin.x);
			tempttb->Bits=new BYTE[bitsize];
			tempW+=tempttb->realw+m_VSpace;
			if(tempW>Size.cx)
			{
				Size.cy+=(m_TextH+m_HSpace);
				tempW=0;
			}
			bitsize=GetGlyphOutline(m_Hdc, m_WTxt[i], GGO_BITMAP, & m_metrics, tempttb->len, tempttb->Bits, &m_Mat2);
			bitlist->add((LPVOID)tempttb);
		}
		m_Img=new CImgFile();
		m_Img->SetSize(Size.cx,Size.cy);
		m_Img->FillColor(m_BgColor);
		int x,y,tempw;
		x=0;
		y=m_TextH;
		for(i=0;i<txtlen;i++)
		{
			if(x+(tempttb->realw+m_VSpace)>Size.cx)
			{
				x=0;
				y+=(m_TextH+m_HSpace);
			}
			tempttb=(PTrueTypeBit)bitlist->items(i);
			tempw=tempttb->len/tempttb->h;
			if(tempttb->by<tempttb->h)
				m_Img->DrawText256(x+tempttb->bx,y-tempttb->h,tempw,tempttb->h,tempttb->w,m_Color,tempttb->Bits);
			else
				m_Img->DrawText256(x+tempttb->bx,y-tempttb->by,tempw,tempttb->h,tempttb->w,m_Color,tempttb->Bits);
			x+=(tempttb->realw+m_VSpace);
		}
		m_Img->SetMake(true);
		ClearBitList();
		W=Size.cx;
		H=Size.cy;
	}
}